/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package Compresor;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.PrintStream;
import java.io.Serializable;
import java.util.HashMap;
import java.util.jar.Attributes;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 *
 * @author asc
 */
public class Huffman implements Serializable
{
    private Diccionario Dic;
    private String Nombre;
    private int nBits;
            
    public String comprime(String Fichero)
    {
        String[] x = Fichero.split("/");
        Nombre=(x[x.length-1]);
        
        LexicalAnalisis Lex = new LexicalAnalisis(Fichero);
        Lex.AnalizeInput1Char();

        Dic = new Diccionario();
        HashMap<String,String> codificacion = Dic.Huffman(Lex);
        
        StringBuilder Coded = new StringBuilder();
        Lex.inicializaFichero();
        double i=0;
        double tam=Lex.Final();
        while(Lex.Final()!=0)
        {
            System.out.println(i + ":" + tam + " - " + i/tam);
            String tokken = Character.toString(Lex.getNextChar());
            Coded.append(codificacion.get(tokken));
            //System.out.println(tokken + "\t" + Coded.toString());
            i++;
        }
        Lex.cierraFichero();
        //System.out.println(Coded.toString());
        nBits=Coded.length();
        return Coded.toString();
    }
    
    public void descomprime(String tmp)
    {
        StringBuilder out = new StringBuilder();
        
        HashMap<String,String> translate = Dic.getTablaRoseta();
        BNode x = new BNode("");
        
        for(String a : translate.keySet())
        {
            BNode y = x;
            for(int i=0; i<a.length(); i++)
            {
                if(a.charAt(i) == '0')
                {
                    if(y.leftBNode == null)
                    {
                        y.leftBNode = new BNode(y.anyClass + "");
                    }
                    y=y.leftBNode;
                }
                else if(a.charAt(i) == '1')
                {
                    if(y.rightBNode == null)
                    {
                        y.rightBNode = new BNode(y.anyClass + "");
                    }
                    y=y.rightBNode;
                }
            }
            y.anyClass=translate.get(a);
            System.out.println(a.toString() + "-" + translate.get(a));
        }
        int i=0;
        while(i<nBits)
        {
            System.out.println(i + ":" + nBits + " - " + (double)i/(double)nBits);
            boolean findTrad=false;
            String trad = "";
            BNode y = x;
            while(!findTrad && i<=nBits)
            {
                if(y.anyClass.length()!=0)
                {
                    System.out.println(y.anyClass);
                    out.append(y.anyClass);
                    findTrad=true;
                }
                else if(i<nBits)
                {
                    y=(tmp.charAt(i) == '0')? y.leftBNode: y.rightBNode;
                    i++;
                }
                
                /*
                trad+= tmp.charAt(i);
                System.out.println(trad.toString());
                if(translate.containsKey(trad))
                {
                    findTrad=true;
                    out+=translate.get(trad);
                }
                */
            }
        }
        //System.out.println(out);
        FileOutputStream fos;
        try {
            fos = new FileOutputStream(Nombre);
            PrintStream ps = new PrintStream(fos);
            ps.print(out.toString());
            ps.close();
            fos.close();
        } 
        catch (Exception ex) 
        {
            Logger.getLogger(Huffman.class.getName()).log(Level.SEVERE, null, ex);
        }
        
    }
}


class BNode {

    public BNode leftBNode,  rightBNode; // the nodes
    public String anyClass; //the AnyClass objext

    public BNode(String anyClass ) {//constructor
        this.anyClass= anyClass;
        this.leftBNode = null;
        this.rightBNode = null;
    }
}